import time

from . import const
from deploy.workers.deploy_base import DeployBase
from eval_lib.common.logger import get_logger
from .dfenvs import DFEnvs
from common import utils
from .workers.deepflow_ce import DeployDeepflowCE
from common.module import DeployMeta

log = get_logger()


class DeployWorker():

    def __init__(self, meta: DeployMeta):
        self.deploys = []
        self.meta = meta
        self.env_uuid = self.meta.uuid
        self.deploy_timeout = 30 * 60
        self.start_time = int(time.time())
        self.redis_envs = DFEnvs(self.env_uuid)
        self.Platform = utils.choose_platform()

    def deploy(self) -> bool:
        for index in range(self.meta.amount):
            if self.meta.type == const.ENV_TYPE_DEEPFLOW_CE:
                instance_name = f"{self.meta.instance_name}-{index}"
                deploy_tool = DeployDeepflowCE(
                    uuid=self.env_uuid,
                    instance_name=instance_name,
                    df_server_image_tag=self.meta.df_server_image_tag,
                    df_agent_image_tag=self.meta.df_agent_image_tag
                )
                deploy_tool.start()
                self.deploys.append(deploy_tool)
            else:
                log.error(f"UNKNOWN TYPE: {self.meta.type}")
        log.info(
            f'{self.env_uuid} deepflow start deploy, number is {self.meta.amount}'
        )
        while self.deploys:
            for index, deploy in enumerate(self.deploys):
                if deploy.is_alive():
                    time_usage = int(time.time()) - self.start_time
                    if time_usage > self.deploy_timeout:
                        log.info(f"timeout! kill deploy process {deploy}")
                        deploy.terminate()
            # 保留存活的进程
            self.deploys = [deploy for deploy in self.deploys if deploy.is_alive()]
            time.sleep(10)

        available_df_env_num = self.redis_envs.update_reserved()
        if available_df_env_num < self.meta.amount:
            log.error(
                f"only {available_df_env_num} df_envs available, but {self.meta.amount} required"
            )
        else:
            log.info("all df_envs are available")
        if available_df_env_num == 0:
            return False
        else:
            envs = self.redis_envs.get_all_envs()
            log.info(
                f"all instance_names of df_env: {[env_name for env_name,_ in envs.items()]}"
            )
            return True

    def release(self):
        instance_names = []
        for _, env in self.redis_envs.get_all_envs().items():
            self.redis_envs.delete_by_instance_name(env["name"])
            if env["deploy_status"] != "complete":
                instance_names.append(env["name"])
        if instance_names:
            log.info(f"delete instances: {instance_names}")
            self.Platform.delete_instances(instance_names)
        self.redis_envs.delete_envs_by_uuid()

